package de.hsb.ai.learning;

import java.util.Iterator;
import java.util.List;
import java.util.Random;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import weka.classifiers.Classifier;
import weka.classifiers.Evaluation;
import weka.classifiers.bayes.NaiveBayes;
import weka.classifiers.lazy.IBk;
import weka.classifiers.trees.J48;
import weka.core.Instances;
import de.hsb.ai.util.ScotlandJadeGameLogger.Entry;
import de.hsb.ai.util.ScotlandJadeHelper;

public class ClassificationHelper {
	
	public static final Logger logger = LoggerFactory.getLogger("sy.classify");
	
	private Instances rawData;
	
	public ClassificationHelper(Instances data) {
		this.rawData = data;
	}
	
	public void train(int runs, int folds, Classifier cls) throws Exception {
		long randSeed = 42L;
		
		for (int i = 0; i < runs; ++i) {
			Instances randData = new Instances(rawData);
			randomizeData(randData, randSeed + i);
			randData.stratify(folds);
			
			Evaluation eval = new Evaluation(randData);
			
			for (int n = 0; n < folds; ++n) {
				Instances train = randData.trainCV(folds, n);
				Instances test = randData.testCV(folds, n);
				
				logger.debug("CV: test-values: " + test.numInstances() + "train-values: " + train.numInstances());
				
				Classifier trainCls = Classifier.makeCopy(cls);
				trainCls.buildClassifier(train);
				eval.evaluateModel(trainCls, test);
			}
			
			logger.info(eval.toSummaryString());
		}
	}

	public static void randomizeData(Instances data, long seed) {
		data.randomize(new Random(seed));
	}

	public void classify(weka.classifiers.Classifier classifier) throws Exception {
		classifier.buildClassifier(rawData);
	
		Evaluation evaluation = new Evaluation(rawData);
		evaluation.evaluateModel(classifier, rawData);
		
		logger.info(evaluation.toSummaryString());
	}
	
	public static void main(String[] args) {
		Iterator<List<Entry>> iterator = ScotlandJadeHelper.createGameLogger().read().iterator();
		Instances data = FugitiveAnalysis.load(iterator);
		data.setClassIndex(data.numAttributes()-1);
		ClassificationHelper helper = new ClassificationHelper(data);
		Classifier classifiers[] = {new NaiveBayes(), new J48(), new IBk(3)};
//		((NaiveBayes) classifier).setUseSupervisedDiscretization(true);
		for (Classifier cls : classifiers)
		{
			try {
				helper.train(1, 10, cls);
			} catch (Exception e) {
				logger.error("classifying", e);
			}
		}
	}

}
